
package com.joysuch.wwyt.quartz.bp;

import com.joysuch.wwyt.bp.entity.BpDeviceFacilityRepairRecord;
import com.joysuch.wwyt.bp.entity.BpProductionFacility;
import com.joysuch.wwyt.bp.entity.BpTaskList;
import com.joysuch.wwyt.bp.enums.DeviceFacilityLifecycles;
import com.joysuch.wwyt.bp.enums.DeviceFacilityMaintainStates;
import com.joysuch.wwyt.bp.enums.DeviceFacilityRepairStates;
import com.joysuch.wwyt.bp.repository.BpDeviceFacilityMaintainRecordDao;
import com.joysuch.wwyt.bp.repository.BpDeviceFacilityRepairRecordDao;
import com.joysuch.wwyt.bp.repository.BpProductionFacilityDao;
import com.joysuch.wwyt.bp.repository.BpTaskListDao;
import com.joysuch.wwyt.core.quartz.ResetTimeSequenceBizCodesSeedJob;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 定时任务实现如下功能:
 * <ul>
 * <li>1. 定时更新设备维修状态</li>
 * </ul>
 *
 * @author zhangxiaohuan
 * @company huanke
 * @date 2019年12月15日 下午12:35:52
 * @since
 */
@Service
@Slf4j
public class CheckDeviceFacilityStateJob {

    private static final Logger logger = LoggerFactory.getLogger(ResetTimeSequenceBizCodesSeedJob.class);

    @Autowired
    private BpProductionFacilityDao bpProductionFacilityDao;
    @Autowired
    private BpDeviceFacilityRepairRecordDao bpDeviceFacilityRepairRecordDao;
    @Autowired
    private BpTaskListDao taskListDao;
    @Autowired
    private BpDeviceFacilityMaintainRecordDao bpDeviceFacilityMaintainRecordDao;

    @Transactional
    @Scheduled(cron = "0 */10 * * * ?")
    public void check() {
        try {
            Date date = new Date();
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            cal.add(Calendar.MINUTE, -10);
            Date beforeDate = cal.getTime();
            //查看前维修 保养结束时间大于10分钟前的数据 减少查询量
            List<BpProductionFacility> updateList = new ArrayList<>();
            //维修
            List<BpProductionFacility> rList = bpProductionFacilityDao.getNeedRepairCheckFacility(beforeDate);
            Integer state = null;
            if (!CollectionUtils.isEmpty(rList)) {
                for (BpProductionFacility facility : rList) {
                    state = editRepairState(facility, date);
                    if (facility.getRepairState() == null || !facility.getRepairState().equals(state)) {
                        facility.setRepairState(state);
                        updateList.add(facility);
                    }
                }

            }
            //保养
            List<BpProductionFacility> mList = bpProductionFacilityDao.getNeedMaintainCheckFacility(beforeDate);
            if (!CollectionUtils.isEmpty(mList)) {
                for (BpProductionFacility facility : mList) {
                    state = editMaintainState(facility, date);
                    if (facility.getMaintainState() == null || !facility.getMaintainState().equals(state)) {
                        facility.setMaintainState(state);
                        updateList.add(facility);
                    }
                }
            }
            if (updateList.size() > 0) {
                bpProductionFacilityDao.saveAll(updateList);
            }
        } catch (Exception e) {
            logger.error("设备装置处理出错", e);
        }
    }

    private Integer editRepairState(BpProductionFacility facility, Date date) {
        //维修
        int r = bpDeviceFacilityRepairRecordDao.countByDeviceFacilityIdAndNowDate(facility.getId(), date);
        if (r > 0) {
            return DeviceFacilityRepairStates.REPAIRING.getId();
        } else {
            return DeviceFacilityRepairStates.OK.getId();
        }
    }

    private Integer editMaintainState(BpProductionFacility facility, Date date) {
        //保养
        int m = bpDeviceFacilityMaintainRecordDao.countByDeviceFacilityIdAndNowDate(facility.getId(), date);
        if (m > 0) {
            return DeviceFacilityMaintainStates.Maintain.getId();
        } else {
            return DeviceFacilityMaintainStates.OK.getId();
        }
    }

    private void processFacility(BpProductionFacility cert, Date now, Map<Long, BpDeviceFacilityRepairRecord> map) {
        BpDeviceFacilityRepairRecord record = map.get(cert.getId());
        if (record != null) {
            if (now.compareTo(record.getRepairStartDate()) >= 0 && now.compareTo(record.getRepairEndDate()) <= 0) {
                cert.setRepairState(DeviceFacilityRepairStates.REPAIRING.getId());
            } else {
                cert.setRepairState(DeviceFacilityRepairStates.OK.getId());
            }
        }
    }

    /**
     * 定时生成保养提醒消息。<br>
     * 以设备生成时间为保养周期的起始时间T + M*N 为第N次保养的时间<br>
     * 只有保养周期填写的设备才填写，如果提醒周期未填写，默认为1天
     */
    @Transactional
    @Scheduled(cron = "0 15 0 * * ?")
    public void checkMaintainStatus() {
        try {
            logger.info("开始处理设备装置保养任务");
            // quatz使用的是独立的线程，不会包含有Context中相关信息，所以不会被拦截，添加tenentId,orgCode字段。查询出的是所有租户的数据

            // 查询所有的需要保养的设备（填写了保养周期，且未报废的设备）
            List<BpProductionFacility> list = bpProductionFacilityDao
                    .findNeedMaintainFailicities(DeviceFacilityLifecycles.SCRAPED.getId());
            if (list.isEmpty()) {
                return;
            }
            int count = 0;
            java.time.LocalDate now = java.time.LocalDate.now();
            for (BpProductionFacility cert : list) {
                if (isDeviceNeedMaintain(cert, now)) {
                    createMaintainNotice(cert);
                    count++;
                }
            }
            logger.info("设备装置保养提醒处理完成,共生成{}条提醒", count);
        } catch (Exception e) {
            logger.error("设备装置保养提醒处理出错", e);
        }
    }

    // 生成保养通知
    private void createMaintainNotice(BpProductionFacility cert) {
        BpTaskList task = new BpTaskList();
        task.setDataId(cert.getId());
        task.setDetail(String.format("%s需要保养，请提前安排", cert.getName()));
        task.setUserId(cert.getPersonInChargeId());
        task.setModule("设备装置");
        task.setTenentId(cert.getTenentId());
        task.setOrgCode(cert.getOrgCode());
        task.setState(1);
        taskListDao.save(task);
    }

    private boolean isDeviceNeedMaintain(BpProductionFacility cert, java.time.LocalDate now) {
        int remindAheadDays = cert.getRemindAheadDays() == null
                || cert.getRemindAheadDays() > cert.getMaintainPeriodDays() ? 1 : cert.getRemindAheadDays();
        // 计算当前日期和创建日期的 差距天数（创建时间取整到天，当前时间也取整到天)
        long diffDays = daysDiff(cert.getCreateTime(), now);
        System.err.println(cert.getName() + " diff days = " + diffDays);
        return (diffDays >= 0 && (diffDays + remindAheadDays) % cert.getMaintainPeriodDays() == 0);
    }

    private long daysDiff(LocalDateTime createTime, java.time.LocalDate now) {
        return now.toEpochDay() - createTime.toLocalDate().toEpochDay();
    }
}
